/*
 * Eugen Stoian <stoian.e@gmail.com> 2010
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "MathPlotter.h"
#include "ui_MathPlotter.h"
#include "Project.h"
#include "Expression3DFrame.h"
#include "Parametric3DFrame.h"
#include "AboutDialog.h"
#include "HelpAssistant.h"
#include <QMessageBox>
#include <QDir>

#include <QFileDialog>
MathPlotter::MathPlotter(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MathPlotter)
{
    _helpAssistant = new HelpAssistant();
    ui->setupUi(this);
    ui->toolBar->addAction(ui->actionNew);
    ui->toolBar->addAction(ui->action_Open);
    ui->toolBar->addSeparator();
    ui->toolBar->addAction(ui->action_Save);
    ui->toolBar->addAction(ui->actionSave_As);
    _project = new Project("",this);
    ui->widget->setProject(_project);
    _currentFrame = 0;
    _exprFrame = new Expression3DFrame(this);
    _exprFrame->hide();
    _paramFrame = new Parametric3DFrame(this);
    _paramFrame->hide();
    connect(ui->action_Open,SIGNAL(triggered()),this,SLOT(open()));
    connect(ui->action_Save,SIGNAL(triggered()),this,SLOT(save()));
    connect(ui->actionSave_As,SIGNAL(triggered()),this,SLOT(saveAs()));
    connect(ui->widget,SIGNAL(plotSelected(QString)),this,SLOT(showParametric(QString)));
    connect(ui->widget,SIGNAL(expressionSelected(QString)),this,SLOT(showExpression(QString)));
    connect(ui->widget,SIGNAL(unselect()),this,SLOT(showNothing()));
    connect(ui->actionSurface,SIGNAL(triggered()),ui->widget,SLOT(newSurface()));
    connect(ui->actionCurve,SIGNAL(triggered()),ui->widget,SLOT(newCurve()));
    connect(ui->actionExpression,SIGNAL(triggered()),ui->widget,SLOT(newExpression()));
    connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(showAbout()));
    connect(ui->actionContents,SIGNAL(triggered()),this,SLOT(showHelp()));
    this->setWindowTitle("QBernoulli - Unnamed.qbp");

}

MathPlotter::~MathPlotter()
{
    delete ui;
    delete _helpAssistant;
}

void MathPlotter::save(){
    if(_project){
        if(_project->objectName().isEmpty())
            saveAs();
        else{
            QFile file(_project->objectName());
            file.open(QIODevice::WriteOnly);
            QDataStream out(&file);
            out << *_project;
        }
    }
}
void MathPlotter::saveAs(){
    if(_project){
        QString fileName;
        if(_project->objectName().isEmpty())
            fileName = QDir::homePath()+"/Unnamed.qbp";
        else
            fileName = _project->objectName();
        fileName = QFileDialog::getSaveFileName(this,
                                                tr("Save File"),
                                                fileName,
                                                tr("QBernoulli projects (*.qbp)"));
        if(!fileName.isEmpty()){
            QFile file(fileName);
            file.open(QIODevice::WriteOnly);
            QDataStream out(&file);
            out << *_project;
            _project->setObjectName(fileName);
            this->setWindowTitle("QBernoulli - "+fileName);
        }
    }
}
void MathPlotter::open(){
    if(_project){
        QString fileName = QFileDialog::getOpenFileName(this,
                                                        tr("Open File"),
                                                        QDir::homePath(),
                                                        tr("QBernoulli projects (*.qbp)"));
        if(!fileName.isEmpty()){
            QFile file(fileName);
            file.open(QIODevice::ReadOnly);
            QDataStream in(&file);
            _project->cleanUp();
            in >> *_project;
            ui->widget->update();
            _project->setObjectName(fileName);
            this->setWindowTitle("QBernoulli - "+fileName);
        }
    }
}

void MathPlotter::showExpression(const QString& name){
    if(_currentFrame!=0){
        if(_currentFrame!=_exprFrame){
            if(_paramFrame->isModified()){
                QMessageBox msg;
                msg.setText(tr("The setting for the current object have been changed..."));
                msg.setInformativeText(tr("Do you want to apply changes?"));
                msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
                msg.setDefaultButton(QMessageBox::Yes);
                int ret = msg.exec();
                switch (ret) {
                    case QMessageBox::Yes:
                        _paramFrame->apply();
                        break;
                    case QMessageBox::No:
                        _paramFrame->revert();
                        break;
                    default:
                        break;
                }
            }
            _currentFrame->hide();
            ui->frame->layout()->removeWidget(_currentFrame);
        }
        else {
            if(_exprFrame->isModified()){
                QMessageBox msg;
                msg.setText(tr("The setting for the current object have been changed..."));
                msg.setInformativeText(tr("Do you want to apply changes?"));
                msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
                msg.setDefaultButton(QMessageBox::Yes);
                int ret = msg.exec();
                switch (ret) {
                    case QMessageBox::Yes:
                        _exprFrame->apply();
                        break;
                    case QMessageBox::No:
                        _exprFrame->revert();
                        break;
                    default:
                        break;
                }
            }
        }
    }
    Expression3D* expr = _project->findExpression(name);
    if(expr){
        _exprFrame->setExpression(expr);
        qobject_cast<QBoxLayout*>(ui->frame->layout())->insertWidget(0,_exprFrame);
        _exprFrame->show();
        _currentFrame = _exprFrame;
    }
    else{
        _currentFrame = 0;
    }
}

void MathPlotter::showParametric(const QString& name){
    if(_currentFrame!=0){
        if(_currentFrame!=_paramFrame){
                if(_exprFrame->isModified()){
                    QMessageBox msg;
                    msg.setText(tr("The setting for the current object have been changed..."));
                    msg.setInformativeText(tr("Do you want to apply changes?"));
                    msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
                    msg.setDefaultButton(QMessageBox::Yes);
                    int ret = msg.exec();
                    switch (ret) {
                        case QMessageBox::Yes:
                            _exprFrame->apply();
                            break;
                        case QMessageBox::No:
                            _exprFrame->revert();
                            break;
                        default:
                            break;
                    }
                }
            _currentFrame->hide();
            ui->frame->layout()->removeWidget(_currentFrame);
        }
        else {
            if(_paramFrame->isModified()){
                QMessageBox msg;
                msg.setText(tr("The setting for the current object have been changed..."));
                msg.setInformativeText(tr("Do you want to apply changes?"));
                msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
                msg.setDefaultButton(QMessageBox::Yes);
                int ret = msg.exec();
                switch (ret) {
                    case QMessageBox::Yes:
                        _paramFrame->apply();
                        break;
                    case QMessageBox::No:
                        _paramFrame->revert();
                        break;
                    default:
                        break;
                }
            }
        }
    }
    ParametricObject3D* object = _project->findObject(name);
    if(object){
        _paramFrame->setObject(object);
        qobject_cast<QBoxLayout*>(ui->frame->layout())->insertWidget(0,_paramFrame);
        _paramFrame->show();
        _currentFrame = _paramFrame;
    }
    else{
        _currentFrame = 0;
    }
}

void MathPlotter::showNothing(){
    if(_currentFrame){
        ui->frame->layout()->removeWidget(_currentFrame);
        _currentFrame->hide();
    }
    _currentFrame = 0;
}

void MathPlotter::showAbout(){
    AboutDialog dlg;
    dlg.exec();
}
void MathPlotter::showHelp(){
    _helpAssistant->showDocumentation("doc.html");
}
